﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using RIDA.Globals;

namespace RIDA.DiagramDesigner.DragDrop
{
    public class CrossWindowsLayer
    {

        public const int HORIZONTAL_GAP_LINE_MIN_WIDTH = 12;
        public const int ELEMENT_VERTICAL_MARGIN = 2;
        public const int POWER_LINE_MARGIN_FROM_TOP = 49;
        public const int POWER_LINE_WIDTH = 2;
        public const int LINES_SUROUNDING_BORDER_WIDTH = 8;
        public const int PANEL_VERTICAL_PADDING = 25;

        #region Data

        private UIElement _dragElement;
        private ViewModelBase _vm;
        private bool _isDragging;
        private bool _dropActionCalled;
        private bool _dragHasLeftScope = false;
        Window _topMostWindow;
        private Point _previosPoint;
        private bool _initNoCursor = true;
        public Size MaxSize { get; set; }

        #endregion // Data

        #region Constructor
        public CrossWindowsLayer(UIElement dragElement, bool initNoCursor = true)
        {
            _dragElement = dragElement;
            _isDragging = false;
            _dropActionCalled = false;
            _initNoCursor = initNoCursor;
        }
       
        #endregion

       

        #region Private Methods

        public void StartDragDropProcess()
        {
            if (_dragElement == null)
                return;


            _isDragging = true;
            foreach (Window window in Application.Current.Windows)
            {
                window.AllowDrop = true;
                window.Drop += new DragEventHandler(_dragScope_Drop);
                
            }

            GiveFeedbackEventHandler feedbackhandler = new GiveFeedbackEventHandler(dragElement_GiveFeedback);
            _dragElement.GiveFeedback += feedbackhandler;

            _dragHasLeftScope = false;

            CreateDragDropWindow(_dragElement as Visual);

            UpdateWindowLocation();
            this._topMostWindow.Show();

            DataObject dataObject = new DataObject(
                                    System.Windows.DataFormats.StringFormat,
                                  (_dragElement as FrameworkElement).DataContext);

            DragDropEffects de = System.Windows.DragDrop.DoDragDrop(_dragElement, dataObject, DragDropEffects.Copy);

            //after the drop ends
            DestroyDragDropWindow(); 
            foreach (Window window in Application.Current.Windows)
            {
                window.AllowDrop = true;
                _isDragging = true;
                window.Drop -= new DragEventHandler(_dragScope_Drop);
                window.Cursor = null;
            }

            _dragElement.GiveFeedback -= feedbackhandler;
           
            _isDragging = false;

        }

        void dragElement_GiveFeedback(object sender, GiveFeedbackEventArgs e)
        {
            UpdateWindowLocation();
            e.UseDefaultCursors = false; 
            e.Handled = true;
        }

        private void UpdateWindowLocation()
        {
            Point _currentMousePoint = MouseUtilities.GetMousePositionFromScreen();

            if (_previosPoint != _currentMousePoint)
            {
                _topMostWindow.Left = _currentMousePoint.X;
                _topMostWindow.Top = _currentMousePoint.Y;
            }
            _previosPoint = _currentMousePoint;
        }

        void _dragScope_Drop(object sender, DragEventArgs e)
        {
            _dropActionCalled = true;

            
        }

        void dragElement_QueryContinueDrag(object sender, QueryContinueDragEventArgs e)
        {
            if (this._dragHasLeftScope)
            {
                e.Action = DragAction.Cancel;
                e.Handled = true;
            }
        }

        private void CreateDragDropWindow(Visual dragElement)
        {
            this._topMostWindow = new Window();
            _topMostWindow.WindowStyle = WindowStyle.None;
            _topMostWindow.AllowsTransparency = true;
            _topMostWindow.AllowDrop = false;
            _topMostWindow.Background = null;
            _topMostWindow.IsHitTestVisible = false;
            _topMostWindow.SizeToContent = SizeToContent.WidthAndHeight;
            _topMostWindow.Topmost = true;
            _topMostWindow.ShowInTaskbar = false;
            _topMostWindow.SourceInitialized += new EventHandler(
            delegate(object sender, EventArgs args)
            {
                PresentationSource windowSource = PresentationSource.FromVisual(this._topMostWindow);
                IntPtr handle = ((System.Windows.Interop.HwndSource)windowSource).Handle;

                Int32 styles = Win32.GetWindowLong(handle, Win32.GWL_EXSTYLE);
                Win32.SetWindowLong(handle, Win32.GWL_EXSTYLE, styles | Win32.WS_EX_LAYERED | Win32.WS_EX_TRANSPARENT);

            });

            (dragElement as UIElement).Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
            this._topMostWindow.Content = dragElement;
            UpdateWindowLocation();
        }

        private void DestroyDragDropWindow()
        {
            if (this._topMostWindow != null)
            {
                this._topMostWindow.Close();
                this._topMostWindow = null;
            }
        }

        #endregion
    }
}
